<template>
  <div
    ref="customFormRef"
    class="custom-form"
    :style="{
      '--columns': columns,
      '--labelBgColor': isEditable ? 'transparent' : '#f9f9f9'
    }"
  >
    <slot v-if="title" name="title">
      <div class="form-title" style="">
        <span class="title">{{ title }}</span>
      </div>
    </slot>
    <el-form ref="ruleFormRef" :model="form" width="100%" :label-width="labelWidth" class="demo-ruleForm" status-icon :hide-required-asterisk="!isEditable">
      <template v-for="item in createItemList">
        <template v-if="item.type == 'input' || item.type == 'textarea'">
          <el-form-item :label="item.label" :prop="item.name" :class="item.name" :key="item.name" :rules="item.rules">
            <el-input v-if="isEditable" v-model="form[item.name]" :placeholder="'请输入' + item.label" :type="item.type" v-bind="item.attrs || {}">
              <template v-if="item.prepend" #prepend>{{ item.prepend }}</template>
              <template v-if="item.append && typeof item.append == 'string'" #append>
                {{ item.append }}
              </template>
              <template v-if="item.append" #append>
                {{ item.append }}
                <!-- <el-select v-model="select" placeholder="Select" style="width: 80px">
                  <el-option :label="subItem.label" :value="subItem.value" v-for="subItem in item.append" :key="subItem.value" />
                </el-select> -->
              </template>
            </el-input>
            <div v-else class="view">{{ form[item.name] }} {{ item.append }}</div>
          </el-form-item>
        </template>
        <template v-if="item.type == 'inputNumber' && !item.hidden">
          <el-form-item :label="item.label" :prop="item.name" :class="item.name" :key="item.name" :rules="item.rules">
            <el-input-number v-if="isEditable" v-model="form[item.name]" :placeholder="'请选择' + item.label" v-bind="item.attrs || {}" />
            <div v-else class="view">{{ form[item.name] }}</div>
          </el-form-item>
        </template>

        <template v-if="item.widget == 'dropdownSelect'">
          <el-form-item :label="item.label" :prop="item.name" :class="item.name" :key="item.name" :rules="item.rules">
            <el-tree-select
              :collapse-tags="false"
              v-model="form[item.name]"
              node-key="zddm"
              :placeholder="'请选择' + item.label"
              :data="item.options ? item.options : optionsData[item.name]"
              :render-after-expand="false"
              style="width: 240px"
              :key="item.name"
              :multiple="item.multiple"
              @click="getOptions(item)"
              :props="{
                label: 'zdzw'
              }"
              popper-class="customForm-select-popper"
            />
          </el-form-item>
        </template>
        <!-- <template v-if="item.widget == 'dropdownSelect' && item.multiple !== true">
          <el-form-item :label="item.label"  :prop="item.name" :class="item.name" :key="item.name" :rules="item.rules">
            <el-popover placement="bottom" class="custom-form-popover" :width="400" trigger="click" :visible="activePopover == item.name + 'Popover'" :key="item.name">
              <el-table v-loading="loading" :id="'optionsTable' + item.name" :data="item.options ? item.options : optionsData[item.name]" style="width: 100%" height="200px" @row-click="getOptions(item, $event, 2)">
                <el-table-column v-if="item.multiple === true" type="selection"></el-table-column>
                <el-table-column prop="zddm" label="字典代码" width="170" />
                <el-table-column prop="zdzw" label="字典中文" width="200" />
              </el-table>
              <div class="bth">
                <el-button v-if="item.multiple === true" type="primary" @click.stop="confirm">确定</el-button>
                <el-button type="primary" @click.stop="reselect"> 重选</el-button>
                <el-button type="primary" plain @click.stop="cancelSelect">取消</el-button>
              </div>
              <template #reference>
                <el-select v-model="form[item.name]" :placeholder="'请选择' + item.label" @click.stop="getOptions(item)">
                  <template #label>
                    {{ (optionsData[item.name] && optionsData[item.name][0].zdzw) || '' }}
                  </template>
                </el-select>
              </template>
            </el-popover>
          </el-form-item>
        </template>

        <template v-if="item.widget == 'dropdownSelect' && item.multiple === true">
          <el-form-item :label="item.label"  :prop="item.name" :class="item.name" :key="item.name" :rules="item.rules">
            <el-select v-if="isEditable" v-model="form[item.name]" :placeholder="'请选择' + item.label" v-bind="item.attrs || {}" multiple>
              <template v-if="item.options">
                <el-option v-for="subItem in item.options" :label="subItem.zdzw || ''" :value="item.valueType ? subItem[item.valueType] : subItem.zddm" :key="subItem.zddm" />
              </template>
              <template v-else>
                <el-option v-for="subItem in optionsData[item.name]" :label="subItem.zdzw || subItem.JSMC || ''" :value="subItem.zddm || subItem.JSMS || ''" :key="subItem.zddm" />
              </template>
            </el-select>
            <div v-else class="view">{{ form[item.name] }}</div>
          </el-form-item>
        </template> -->
        <template v-if="item.type == 'picker' && !item.hidden">
          <el-form-item :label="item.label" :prop="item.name" :class="item.name" :key="item.name" :rules="item.rules">
            <el-date-picker v-if="isEditable" v-model="form[item.name]" :placeholder="'请选择' + item.label" v-bind="Object.assign({}, { 'value-format': 'YYYY-MM-DD' }, item.attrs)" />
            <div v-else class="view">{{ form[item.name] }}</div>
          </el-form-item>
        </template>
        <template v-if="item.type == 'timePicker' && !item.hidden">
          <el-form-item :label="item.label" :prop="item.name" :class="item.name" :key="item.name" :rules="item.rules">
            <el-time-picker v-if="isEditable" v-model="form[item.name]" :placeholder="'请选择' + item.label" v-bind="Object.assign({}, { 'value-format': 'HH-mm-SS' }, item.attrs)" />
            <div v-else class="view">{{ form[item.name] }}</div>
          </el-form-item>
        </template>
        <template v-if="item.type == 'radio-group'">
          <el-form-item :label="item.label" :prop="item.name" :class="item.name" :key="item.name" :rules="item.rules">
            <el-radio-group v-if="isEditable" v-model="form[item.name]" v-bind="item.attrs || {}">
              <el-radio :label="subItem.zdzw" :value="subItem.zddm" v-for="subItem in item.options" :key="subItem.zddm" />
            </el-radio-group>
            <div v-else class="view">{{ form[item.name] }}</div>
          </el-form-item>
        </template>
        <template v-if="item.type == 'img'">
          <el-form-item :prop="item.name" :key="item.name" class="img" :rules="item.rules">
            <div v-if="isEditable">
              <img src="@/assets/image/no_photo.png" class="image" />

              <el-upload v-model:file-list="uploadFileList" class="upload-demo" action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" multiple :limit="3">
                <el-button type="primary">Click to upload</el-button>
                <template #tip>
                  <div class="el-upload__tip">jpg/png files with a size less than 500KB.</div>
                </template>
              </el-upload>
            </div>

            <div v-else class="view">
              <img src="@/assets/image/no_photo.png" class="image" />
            </div>
          </el-form-item>
        </template>
        <template v-if="item.type == 'upload'">
          <el-form-item :label="item.label" :prop="item.name" :class="item.name" :key="item.name" :rules="item.rules">
            <div v-if="isEditable">
              <input type="file" ref="fileUploadRef" multiple style="display: none" @input="onFileChange($event)" />
              <el-input v-model="form[item.name]" placeholder="请选择文件" />
              <el-button type="primary" class="add" plain @click="handleUploadClick"
                ><el-icon><UploadFilled /></el-icon>选择文件</el-button
              >
            </div>

            <div v-else class="view">
              <img :src="form[item.name] + '?token=' + userStore.token" class="image" />
            </div>
          </el-form-item>
        </template>
      </template>
      <el-form-item v-if="props.showSearchBtn" label="" class="search-btn">
        <el-button class="reset" @click="emit('reset')">
          <el-icon>
            <RefreshLeft />
          </el-icon>
          重置
        </el-button>
        <el-button type="primary" @click="emit('search')">
          <el-icon>
            <Search />
          </el-icon>
          查询
        </el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup name="CustomForm">
import { ref, reactive, computed, onMounted, onBeforeUnmount, onUnmounted, watch, nextTick } from 'vue'

import { stores } from '@/stores/index.js'

import { http } from '@/utils/index'

const userStore = stores.useUserStore()
const dynamicParamsStore = stores.useDynamicParamsStore()

// const form = defineModel('form', { default: {} }) // 组件v-model 绑定的值
const form = defineModel('form') // 组件v-model 绑定的值
console.log(form.value)
const props = defineProps({
  editable: {
    type: Boolean,
    default: false
  },

  showSearchBtn: {
    type: Boolean,
    default: false
  },
  title: {
    type: String,
    default: ''
  },
  titleHeight: {
    type: [String, Number],
    default: '50rem'
  },
  labelWidth: {
    type: String,
    default: '100rem'
  },

  //每行显示几个表单项
  columns: {
    type: [String, Number],
    default: 3
  }
})
// const tableRef = ref()

const fileUploadRef = ref()
const activePopover = ref('')
const activeSelect = ref({})
const loading = ref(false)
const originData = JSON.stringify(form.value) //备份数据，用于重置表单
const isEditable = ref(props.editable)
const customFormRef = ref()
const ruleFormRef = ref()
const selection = ref([]) //下拉框多选
const selectedFile = ref({})

//读取所有的form-item 项
const files = import.meta.glob(['./type/*.js'], { eager: true })
const fieldList = ref([])
for (const key in files) {
  fieldList.value = fieldList.value.concat(files[key].default)
}
//el-select或el-cascader 类型的 option选项数据
const optionsData = ref({})
const uploadFileList = ref([]) //上传的文件
const lastWidth = ref('')
//需要渲染的form-item 列表
const createItemList = computed(() => {
  const arr = []
  for (const key in props.form) {
    if (key == 'YWFZMC') {
      console.log(props.form[key] === null)
    }
    fieldList.value.find((item) => {
      if (item.name == key && props.form[key] !== null) {
        //如果需要验证，设置验证失败提示信息
        if (item.rules?.required) {
          switch (item.type || item.widget) {
            case 'input':
            case 'textarea':
              // !item.rules.message && (item.rules.message = '请输入' + item.label)
              item.rules.message ??= '请输入' + item.label
              break
            case 'select':
            case 'dropdownSelect':
            case 'cascader':
            case 'timePicker':
              item.rules.message ??= '请选择' + item.label
              break
            case 'fileName':
              item.rules.message = '请选择文件'
              break
          }
          item.rules.trigger = 'blur'
        }
        arr.push(item)
        return
      }
    })
  }
  return arr
})
//设置最后一个 from-item项 填满整个行
const setItemStyle = () => {
  const columns = props.columns * 1
  const obj = {}

  for (const key in form.value) {
    if (form.value[key] !== null) {
      obj[key] = form.value[key]
    }
  }

  console.log(form)
  const rows = Math.ceil(Object.keys(obj).length / columns)
  const columnSpan = columns + 1 - (Object.keys(obj).length % columns)
  const ele = customFormRef.value.getElementsByClassName(Object.keys(obj)[Object.keys(obj).length - 1])[0]
  // if (ele) {
  ele.style = `grid-area: ${rows} / ${Object.keys(obj).length % columns} / span 1 / span ${columnSpan};`
  // }
}
watch(
  form,
  (newVal) => {
    if (isEditable.value) {
      console.log(newVal)
      const needRequstItem = []
      for (const key in newVal) {
        createItemList.value.find((item) => {
          if (item.name == key && (item.widget == 'dropdownSelect' || item.widget == 'select') && item.api != '') {
            needRequstItem.push(item)
          }
        })
      }
      console.log(needRequstItem)
      needRequstItem.forEach((item) => {
        getOptions(item)
      })
    }
  },
  {
    // immediate: true,
    deep: true
  }
)
watch(
  isEditable,
  (newVal) => {
    if (newVal) {
      createItemList.value.forEach((item) => {
        if ((item.widget == 'dropdownSelect' || item.widget == 'select') && !item.options && item.api != '') {
          console.log(item)
          // requestData(item)
          getOptions(item)
        }
      })
    }
  },
  {
    // immediate: true,
    deep: true
  }
)
computed(() => {
  customFormRef.value.getElementsByClassName('el-form')[0].offsetWidth
})

onMounted(() => {
  console.log('form-mounted----')
  // if (isEditable.value) {
  //   createItemList.value.forEach((item) => {
  //     if (item.type == 'select' && !item.options && item.api != '') {
  //       console.log(item)
  //       requestData(item)
  //     }
  //   })
  // }
  setItemStyle()
  nextTick(() => {
    lastWidth.value = customFormRef.value.getElementsByClassName('el-form')[0].offsetWidth / 3 + 'px'
    // console.log(lastWidth.value)
  })
  // if (props.editable) {
  //   createItemList.value.forEach((item) => {
  //     console.log(item)
  //     if (item.widget == 'dropdownSelect' && !item.options && item.api != '') {
  //       console.log(11111111)

  //       // requestData(item)
  //       getOptions(item)
  //     }
  //   })
  // }
})
onBeforeUnmount(() => {
  //重置表单数据
  form.value = JSON.parse(originData)
  ruleFormRef.value.resetFields()
})

//请求数据
// const requestData = (obj) => {
//   console.log(obj.field)
//   if (obj.field == 'SSHJ') {
//     //需要特殊处理的字段
//     setTimeout(() => {
//       optionsData.value[obj.field] = [
//         {
//           zdzw: '逮捕',
//           zddm: '1'
//         },
//         {
//           zdzw: '上诉',
//           zddm: '2'
//         },
//         {
//           zdzw: '已判刑',
//           zddm: '3'
//         }
//       ]
//     }, 3000)
//   } else {
//     http(
//       obj.api,
//       obj.methods,
//       Object.assign(obj.params, {
//         unit: userStore.userInfor.unitCode[0],
//         inputValue: '',
//         model: '3'
//       })
//     ).then((res) => {
//       if (res.status == 200) {
//         optionsData.value[obj.field] = res.data.records || res.data || []
//       }
//     })
//   }
// }
//获取下拉框获取选项数据
const getOptions = (selectConfig) => {
  //el-select预设了选项值
  if (selectConfig.options?.length > 0) {
    optionsData.value[selectConfig.name] = selectConfig.options
  } else {
    //普通接口请求数据
    if (selectConfig.api) {
      //从接口请求数据
      loading.value = true
      const params = JSON.parse(JSON.stringify(selectConfig.params))
      //匹配请求参数中的动态参数{xxx}
      for (const key in params) {
        const dynamicpParam = /{([^}]+)}/.exec(params[key])?.[1]
        if (dynamicpParam) {
          if (dynamicpParam == 'dwdm') {
            params[key] = dynamicParamsStore.dynamicParams['treeNode']?.zddm || null
          } else {
            params[key] = dynamicParamsStore.dynamicParams[dynamicpParam] || null
          }
        }
      }
      http(selectConfig.api, selectConfig.method || 'get', params)
        .then((res) => {
          optionsData.value[selectConfig.name] = res.data || res.data.record || []
        })
        .finally(() => {
          loading.value = false
        })
    } else {
      //低代码数据格式请求数据
      loading.value = true
      http(props.api, 'post', {
        codeTableName: selectConfig.downSelectDataName,
        inputValue: row.zddm || '',
        unit: userInfor.currentUnitCode,
        model: model,
        rules: '',
        dwlx: userInfor.dwlx
      })
        .then((res) => {
          optionsData.value[selectConfig.name] = res.data || res.data.record || []
          if (optionsData.value[selectConfig.name].length == 1) {
            form.value[selectConfig.name] = optionsData.value[selectConfig.name][0].zddm
            activePopover.value = ''
          }
        })
        .finally(() => {
          loading.value = false
        })
    }
  }
}
const getOptions2 = (selectConfig, row = {}, model = 1) => {
  activeSelect.value = selectConfig
  activePopover.value = selectConfig.name + 'Popover'

  //el-select预设了选项值
  if (selectConfig.options && row) {
    optionsData.value[selectConfig.name] = []
    optionsData.value[selectConfig.name].push(row)
    form.value[selectConfig.name] = row.zddm
    if (Object.keys(row).length != 0) {
      activePopover.value = ''
    }
  } else {
    //普通接口请求数据
    if (selectConfig.api) {
      //从接口请求数据
      if (!row.zddm) {
        loading.value = true
        const params = JSON.parse(JSON.stringify(selectConfig.params))
        //匹配请求参数中的动态参数{xxx}
        for (const key in params) {
          const dynamicpParam = /{([^}]+)}/.exec(params[key])?.[1]
          if (dynamicpParam) {
            if (selectConfig.name == 'jsh' && dynamicpParam == 'dwdm') {
              params[key] = dynamicParamsStore.dynamicParams['treeNode'].zddm || null
            } else {
              params[key] = dynamicParamsStore.dynamicParams[dynamicpParam] || null
            }
          }
        }
        http(selectConfig.api, selectConfig.method || 'get', params)
          .then((res) => {
            optionsData.value[selectConfig.name] = res.data || res.data.record || []
          })
          .finally(() => {
            loading.value = false
          })
      } else {
        //从接口返回的数据中筛选出二级数据
        if (row.children) {
          optionsData.value[selectConfig.name] = optionsData.value[selectConfig.name].find((item) => item.zddm == row.zddm).children
        } else {
          optionsData.value[selectConfig.name] = []
          optionsData.value[selectConfig.name].push(row)
          // form.value[selectConfig.name] = selectConfig.valueType ? optionsData.value[selectConfig.name][0][selectConfig.valueType] : optionsData.value[selectConfig.name][0].zddm
          form.value[selectConfig.name] = optionsData.value[selectConfig.name][0].zddm
          activePopover.value = ''
        }
      }
    } else {
      //低代码数据格式请求数据
      loading.value = true
      http(props.api, 'post', {
        codeTableName: selectConfig.downSelectDataName,
        inputValue: row.zddm || '',
        unit: userInfor.currentUnitCode,
        model: model,
        rules: '',
        dwlx: userInfor.dwlx
      })
        .then((res) => {
          optionsData.value[selectConfig.name] = res.data || res.data.record || []
          if (optionsData.value[selectConfig.name].length == 1) {
            form.value[selectConfig.name] = optionsData.value[selectConfig.name][0].zddm
            activePopover.value = ''
          }
        })
        .finally(() => {
          loading.value = false
        })
    }
  }
}
const reselect = () => {
  getOptions(activeSelect.value)
}
const cancelSelect = () => {
  activePopover.value = ''
}

const setEditable = (val) => {
  isEditable.value = val
}
const confirm = () => {
  console.log('confirm')
}
//选择上传文件后的回调函数
const onFileChange = (event) => {
  const file = event.target.files[0]
  selectedFile.value = file

  if (!file.name.toLowerCase().includes('.apk') || !file.name.toUpperCase().includes('.APK')) {
    event.target.value = ''
    return ElMessage.error('请选择正确的文件类型')
  }
  // addForm.value.fileName = file.name
  console.log(file)
  form.value.file = file
  form.value.fileName = file.name
  // event.target.value = ''
}
const handleUploadClick = () => {
  console.log(fileUploadRef.value[0].click())
}
defineExpose({
  form,
  isEditable,
  setEditable
})
</script>

<style lang="scss" scoped>
div {
  white-space: nowrap;
}

.form-title {
  margin: 6px;
  color: #333333;
  font-size: 16px;
  font-weight: 700;
}

::v-deep(.el-form) {
  display: grid;

  // padding: 10px;

  border: 1px solid #cccccc;
  border-top: none;
  border-right: none;
  border-radius: 4px;

  grid-auto-rows: 38px;
  grid-template-columns: repeat(var(--columns), minmax(0, 1fr));

  // row-gap: 20px;
  .el-form-item {
    margin-bottom: 0 !important;

    border: 1px solid #d69292;
    border-bottom: none;
    border-left: none;

    // border: 1px solid red;
    .el-form-item__label {
      height: 100%;

      background-color: var(--labelBgColor);

      line-height: 38px;
      // padding: 5px;
      // background-color: pink;
    }

    .el-form-item__content {
      height: 100%;
      padding: 0 5px;

      // border: 1px solid yellowgreen;
      .el-form-item__error {
        position: absolute;
        z-index: 1;
        top: -8%;
        left: 50%;
        transform: translateX(-50%);
        background-color: #fff;
      }
    }

    .el-form-item__content > div:not(.el-form-item__error) {
      min-width: 100%;
      // max-width: v-bind(lastWidth);
      // max-width: 100px !important;
    }

    .view {
      height: 100%;
      padding-left: 10px;

      line-height: 38px;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;

      .image {
        margin-top: 2px;
        height: 90%;
      }
    }
  }
}
::v-deep(.el-form-item.fileName) {
  .el-form-item__content {
    display: flex;
    flex-wrap: nowrap !important;
    .el-input {
      // border: 1px solid red;
      min-width: 50% !important;
      margin-right: 15px;
    }
  }
}

.BZ,
.JYAQ {
  min-height: 100px;

  label,
  > div {
    height: 100%;
  }
}

.UNITTYPE,
.APP_LIST {
  // border: 1px solid red;
  .el-select {
    overflow: hidden;
  }
}

:v-deep(.el-form-item__label) {
  background-color: #f9f9f9;
}

.avatar {
  display: block;

  width: 120rem;

  // width: 100%;
  height: 100%;

  // height: 160rem;
  // border: 1px solid red;
}

::v-deep(.el-select) {
  .el-select-tags-wrapper.has-prefix {
    white-space: nowrap;
  }
}
</style>
<style lang="scss">
.el-picker__popper.custom-form-popover {
  overflow: visible !important;
  .bth {
    text-align: center;
    margin-top: 10px;
  }
}
.customForm-select-popper {
  // min-height: 200px;
}
</style>
